package com.example.langchain4j.service;

import cn.hutool.json.JSONUtil;
import com.deepoove.poi.XWPFTemplate;
import com.example.langchain4j.common.constant.PromptConstant;
import com.example.langchain4j.common.exception.BusinessException;
import com.example.langchain4j.utils.DocumentUtils;
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.chat.response.ChatResponse;
import dev.langchain4j.model.input.Prompt;
import dev.langchain4j.model.input.PromptTemplate;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Service
@Slf4j
public class PenaltyDecisionService {

    @Resource
    @Qualifier("chatLanguageModel")
    private ChatLanguageModel chatLanguageModel;

    @Resource
    private ChaiLiangProcessService chaiLiangProcessService;

    private static final String GENERATED_DIR = "src/main/resources/generated";

    /**
     * 生成行政处罚决定书
     * @param caseApprovalJson 立案审批表JSON数据
     * @param interrogationJson 询问笔录JSON数据（可选）
     * @param response HTTP响应
     * @return 返回生成结果
     */
    public Map<String, Object> generatePenaltyDecision(String caseApprovalJson, String interrogationJson, HttpServletResponse response) {
        try {
            log.info("开始生成行政处罚决定书，立案审批表JSON长度: {}", caseApprovalJson.length());

            // TODO: 调用AI模型生成处罚决定书数据
            // 创建提示模板
            String penaltyDecisionPrompt = PromptConstant.generalPenaltyDecision;
            PromptTemplate promptTemplate = PromptTemplate.from(penaltyDecisionPrompt);
            HashMap<String, Object> variables = new HashMap<>();
            variables.put("caseApprovalJson", caseApprovalJson);
            if (interrogationJson != null && !interrogationJson.isEmpty()) {
                variables.put("interrogationJson", interrogationJson);
            }
            Prompt prompt = promptTemplate.apply(variables);

            // 调用模型生成处罚决定书JSON
            ChatResponse chatResponse = chatLanguageModel.chat(prompt.toUserMessage());
            String penaltyDecisionJsonRes = chatResponse.aiMessage().text();

            // 清理JSON字符串，移除可能的markdown标记和推理过程
            penaltyDecisionJsonRes = cleanJsonString(penaltyDecisionJsonRes);

            log.info("------------------------------------------------------------------------------------");
            log.info("生成的处罚决定书JSON：{}", penaltyDecisionJsonRes);

            // 确保generated目录存在
            java.nio.file.Path generatedPath = java.nio.file.Paths.get(GENERATED_DIR);
            if (!java.nio.file.Files.exists(generatedPath)) {
                java.nio.file.Files.createDirectories(generatedPath);
            }

            // 生成文件名
            java.time.format.DateTimeFormatter formatter = java.time.format.DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss");
            String timestamp = java.time.LocalDateTime.now().format(formatter);
            String fileName = "行政处罚决定书_" + timestamp + ".docx";
            String filePath = GENERATED_DIR + "/" + fileName;

            // 填充word模板并保存到文件
            Map<String, Object> resultMap = JSONUtil.toBean(penaltyDecisionJsonRes, Map.class);
            ClassPathResource resource = new ClassPathResource("行政处罚决定书template.docx");
            InputStream templateInputStream = resource.getInputStream();
            XWPFTemplate template = XWPFTemplate.compile(templateInputStream).render(resultMap);

            // 保存到本地文件
            java.io.FileOutputStream fileOut = new java.io.FileOutputStream(filePath);
            template.write(fileOut);
            fileOut.close();
            template.close();

            log.info("处罚决定书文件已保存: {}", filePath);

            // 准备返回结果
            Map<String, Object> result = new HashMap<>();
            result.put("success", true);
            result.put("fileName", fileName);
            result.put("filePath", "http://localhost:8018/api/penalty-decision/generated/" + fileName);
            result.put("jsonData", penaltyDecisionJsonRes);
            result.put("message", "行政处罚决定书生成成功");

            log.info("处罚决定书生成完成，返回结果: {}", result);
            return result;

        } catch (IOException e) {
            log.error("解析文档失败", e);
            throw new BusinessException(500, "解析文档失败: " + e.getMessage());
        } catch (Exception e) {
            log.error("生成处罚决定书失败", e);
            throw new BusinessException(500, "生成处罚决定书失败: " + e.getMessage());
        }
    }

    /**
     * 生成行政处罚决定书 - 完整工作流（包含裁量标准查询和证据文件处理）
     * @param caseApprovalFile 立案审批表文件（原始Word文档）
     * @param interrogationFile 询问笔录文件（可选）
     * @param evidenceFiles 证据文件列表（可选）
     * @param response HTTP响应
     * @return 返回生成结果
     */
    public Map<String, Object> generatePenaltyDecisionFromFile(MultipartFile caseApprovalFile,
                                                                 MultipartFile interrogationFile,
                                                                 MultipartFile[] evidenceFiles,
                                                                 HttpServletResponse response) {
        try {
            log.info("========== 开始生成行政处罚决定书完整工作流 ==========");

            // 步骤1: 提取立案审批表的完整内容
            String caseApprovalContent = DocumentUtils.extractTextFromWord(caseApprovalFile);
            log.info("步骤1: 从立案审批表文件提取内容，长度: {}", caseApprovalContent.length());

            // 步骤2: 提取简要案情（从Word文档中直接提取）
            String caseBrief = extractCaseBrief(caseApprovalContent);
            log.info("步骤2: 提取简要案情，长度: {}", caseBrief != null ? caseBrief.length() : 0);

            // 步骤3: 提取询问笔录内容（如果有）
            String interrogationContent = null;
            if (interrogationFile != null && !interrogationFile.isEmpty()) {
                interrogationContent = DocumentUtils.extractTextFromWord(interrogationFile);
                log.info("步骤3: 从询问笔录文件提取内容，长度: {}", interrogationContent.length());
            }

            // 步骤3.5: 处理证据文件，生成证据清单
            String evidenceFilesList = "";
            if (evidenceFiles != null && evidenceFiles.length > 0) {
                evidenceFilesList = formatEvidenceFileNames(evidenceFiles);
                log.info("步骤3.5: 生成证据清单，内容: {}", evidenceFilesList);
            }

            // 步骤4: 调用裁量标准智能体查询法律依据和罚款金额
            log.info("步骤4: 开始调用裁量标准智能体");
            Map<String, Object> chaiLiangResult = chaiLiangProcessService.processChaiLiangQuery(
                    caseApprovalFile, interrogationFile);
            String chaiLiangAdvice = (String) chaiLiangResult.get("chaiLiangAdvice");
            log.info("步骤4: 裁量标准查询完成，建议长度: {}", chaiLiangAdvice != null ? chaiLiangAdvice.length() : 0);

            // 步骤5: 提取法律依据和罚款金额（从裁量建议中提取）
            Map<String, String> extractedInfo = extractLawBasisAndPunishment(chaiLiangAdvice);
            String lawBasis = extractedInfo.get("lawBasis");
            String punishmentAmount = extractedInfo.get("punishmentAmount");
            log.info("步骤5: 从裁量建议提取 - 法律依据: {}, 罚款金额: {}", lawBasis, punishmentAmount);

            // 步骤6: 调用AI模型生成处罚决定书JSON
            log.info("步骤6: 开始生成处罚决定书JSON");
            String penaltyDecisionPrompt = PromptConstant.generalPenaltyDecision;
            PromptTemplate promptTemplate = PromptTemplate.from(penaltyDecisionPrompt);
            HashMap<String, Object> variables = new HashMap<>();
            variables.put("caseApprovalJson", caseApprovalContent);
            variables.put("interrogationJson", interrogationContent != null ? interrogationContent : "");
            variables.put("caseBrief", caseBrief != null ? caseBrief : "");
            variables.put("chaiLiangAdvice", chaiLiangAdvice);
            variables.put("lawBasis", lawBasis);
            variables.put("punishmentAmount", punishmentAmount);

            Prompt prompt = promptTemplate.apply(variables);

            // 调用模型生成处罚决定书JSON
            ChatResponse chatResponse = chatLanguageModel.chat(prompt.toUserMessage());
            String penaltyDecisionJsonRes = chatResponse.aiMessage().text();

            // 清理JSON字符串，移除可能的markdown标记和推理过程
            penaltyDecisionJsonRes = cleanJsonString(penaltyDecisionJsonRes);

            log.info("------------------------------------------------------------------------------------");
            log.info("生成的处罚决定书JSON：{}", penaltyDecisionJsonRes);

            // 步骤6.5: 将证据清单填入JSON（如果有）
            if (evidenceFilesList != null && !evidenceFilesList.isEmpty()) {
                Map<String, Object> jsonMap = JSONUtil.toBean(penaltyDecisionJsonRes, Map.class);
                jsonMap.put("evidence_files", evidenceFilesList);
                penaltyDecisionJsonRes = JSONUtil.toJsonStr(jsonMap);
                log.info("步骤6.5: 已将证据清单填入JSON: {}", evidenceFilesList);
            }

            // 步骤7: 确保generated目录存在
            java.nio.file.Path generatedPath = java.nio.file.Paths.get(GENERATED_DIR);
            if (!java.nio.file.Files.exists(generatedPath)) {
                java.nio.file.Files.createDirectories(generatedPath);
            }

            // 步骤8: 生成文件名
            java.time.format.DateTimeFormatter formatter = java.time.format.DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss");
            String timestamp = java.time.LocalDateTime.now().format(formatter);
            String fileName = "行政处罚决定书_" + timestamp + ".docx";
            String filePath = GENERATED_DIR + "/" + fileName;

            // 步骤9: 填充word模板并保存到文件
            Map<String, Object> resultMap = JSONUtil.toBean(penaltyDecisionJsonRes, Map.class);
            ClassPathResource resource = new ClassPathResource("行政处罚决定书template.docx");
            InputStream templateInputStream = resource.getInputStream();
            XWPFTemplate template = XWPFTemplate.compile(templateInputStream).render(resultMap);

            // 保存到本地文件
            java.io.FileOutputStream fileOut = new java.io.FileOutputStream(filePath);
            template.write(fileOut);
            fileOut.close();
            template.close();

            log.info("步骤9: 处罚决定书文件已保存: {}", filePath);

            // 准备返回结果
            Map<String, Object> result = new HashMap<>();
            result.put("success", true);
            result.put("fileName", fileName);
            result.put("filePath", "http://localhost:8018/api/penalty-decision/generated/" + fileName);
            result.put("jsonData", penaltyDecisionJsonRes);
            result.put("chaiLiangAdvice", chaiLiangAdvice);
            result.put("caseBrief", caseBrief);
            result.put("lawBasis", lawBasis);
            result.put("punishmentAmount", punishmentAmount);
            result.put("evidenceFiles", evidenceFilesList);
            result.put("message", "行政处罚决定书生成成功");

            log.info("========== 处罚决定书生成完成 ==========");
            return result;

        } catch (IOException e) {
            log.error("解析文档失败", e);
            throw new BusinessException(500, "解析文档失败: " + e.getMessage());
        } catch (Exception e) {
            log.error("生成处罚决定书失败", e);
            throw new BusinessException(500, "生成处罚决定书失败: " + e.getMessage());
        }
    }

    /**
     * 从立案审批表内容中提取简要案情
     * 支持多种格式：
     * 1. "简要案情: xxx"
     * 2. "case_brief": "xxx"
     * 3. JSON格式中的case_brief字段
     */
    private String extractCaseBrief(String content) {
        if (content == null || content.trim().isEmpty()) {
            return null;
        }

        // 尝试从纯文本格式提取 "简要案情: xxx"
        Pattern pattern1 = Pattern.compile("简要案情[:\\s：]+(.+?)(?=\\n|$)", Pattern.DOTALL);
        Matcher matcher1 = pattern1.matcher(content);
        if (matcher1.find()) {
            String brief = matcher1.group(1).trim();
            log.info("从纯文本格式提取到简要案情");
            return brief;
        }

        // 尝试从JSON格式提取 "case_brief": "xxx"
        Pattern pattern2 = Pattern.compile("\"case_brief\"\\s*:\\s*\"(.+?)\"", Pattern.DOTALL);
        Matcher matcher2 = pattern2.matcher(content);
        if (matcher2.find()) {
            String brief = matcher2.group(1).trim();
            log.info("从JSON格式提取到简要案情");
            return brief;
        }

        // 尝试解析整个JSON并提取case_brief字段
        try {
            Map<String, Object> jsonMap = JSONUtil.toBean(content, Map.class);
            if (jsonMap.containsKey("case_brief")) {
                String brief = (String) jsonMap.get("case_brief");
                log.info("从解析的JSON对象提取到简要案情");
                return brief;
            }
        } catch (Exception e) {
            log.debug("内容不是有效的JSON格式，尝试其他提取方式");
        }

        log.warn("未能从立案审批表中提取简要案情");
        return null;
    }

    /**
     * 从裁量建议中提取法律依据和罚款金额
     * 使用正则表达式从AI生成的建议中提取关键信息
     */
    private Map<String, String> extractLawBasisAndPunishment(String chaiLiangAdvice) {
        Map<String, String> result = new HashMap<>();
        result.put("lawBasis", "");
        result.put("punishmentAmount", "");

        if (chaiLiangAdvice == null || chaiLiangAdvice.trim().isEmpty()) {
            return result;
        }

        // 提取法律依据：匹配《xxx法》第x条...
        Pattern lawPattern = Pattern.compile("《[^》]+法》[^。]+?第[^。]+?条[^。]*");
        Matcher lawMatcher = lawPattern.matcher(chaiLiangAdvice);
        if (lawMatcher.find()) {
            result.put("lawBasis", lawMatcher.group().trim());
            log.info("提取到法律依据: {}", result.get("lawBasis"));
        }

        // 提取罚款金额：匹配各种金额格式
        // 匹配: "罚款xxx元"、"处以xxx元罚款"、"xxx-xxx元"等
        Pattern amountPattern = Pattern.compile("(罚款|处以|处罚)\\s*([0-9,，]+(?:-[0-9,，]+)?)\\s*元");
        Matcher amountMatcher = amountPattern.matcher(chaiLiangAdvice);
        if (amountMatcher.find()) {
            String amount = amountMatcher.group(2).trim();
            result.put("punishmentAmount", amount + "元");
            log.info("提取到罚款金额: {}", result.get("punishmentAmount"));
        } else {
            // 尝试匹配单独的金额数字
            Pattern simpleAmountPattern = Pattern.compile("([0-9,，]{4,})\\s*元");
            Matcher simpleAmountMatcher = simpleAmountPattern.matcher(chaiLiangAdvice);
            if (simpleAmountMatcher.find()) {
                result.put("punishmentAmount", simpleAmountMatcher.group(1).trim() + "元");
                log.info("提取到罚款金额（简单格式）: {}", result.get("punishmentAmount"));
            }
        }

        return result;
    }

    /**
     * 格式化证据文件名为规范的证据清单
     * @param evidenceFiles 用户上传的证据文件数组
     * @return 规范的证据清单字符串，如：《消防监督检查记录》《责令限期改正通知书》《询问笔录》
     */
    private String formatEvidenceFileNames(MultipartFile[] evidenceFiles) {
        if (evidenceFiles == null || evidenceFiles.length == 0) {
            return "";
        }

        // 收集所有文件名
        StringBuilder fileNamesBuilder = new StringBuilder();
        for (MultipartFile file : evidenceFiles) {
            if (file != null && !file.isEmpty()) {
                String originalFilename = file.getOriginalFilename();
                if (originalFilename != null && !originalFilename.isEmpty()) {
                    fileNamesBuilder.append(originalFilename).append("\n");
                }
            }
        }

        String fileNames = fileNamesBuilder.toString().trim();
        if (fileNames.isEmpty()) {
            return "";
        }

        log.info("证据文件名列表: {}", fileNames);

        // 调用AI模型格式化证据文件名
        try {
            String formatPrompt = PromptConstant.formatEvidenceFiles;
            PromptTemplate promptTemplate = PromptTemplate.from(formatPrompt);
            HashMap<String, Object> variables = new HashMap<>();
            variables.put("fileNames", fileNames);
            Prompt prompt = promptTemplate.apply(variables);

            ChatResponse chatResponse = chatLanguageModel.chat(prompt.toUserMessage());
            String formattedEvidenceList = chatResponse.aiMessage().text().trim();

            log.info("格式化后的证据清单: {}", formattedEvidenceList);
            return formattedEvidenceList;

        } catch (Exception e) {
            log.error("格式化证据文件名失败", e);
            // 如果AI格式化失败，返回默认证据清单
            return "《消防监督检查记录》《责令限期改正通知书》《询问笔录》《现场照片》";
        }
    }

    /**
     * 清理JSON字符串，移除markdown代码块标记和额外说明
     * 特别处理推理模型（如qwq）的思考过程输出
     */
    private String cleanJsonString(String jsonString) {
        if (jsonString == null || jsonString.trim().isEmpty()) {
            return jsonString;
        }

        String cleaned = jsonString.trim();

        // 移除开头的markdown标记
        if (cleaned.startsWith("```json")) {
            cleaned = cleaned.substring(7);
        } else if (cleaned.startsWith("```")) {
            cleaned = cleaned.substring(3);
        }

        // 移除结尾的markdown标记
        if (cleaned.endsWith("```")) {
            cleaned = cleaned.substring(0, cleaned.length() - 3);
        }

        cleaned = cleaned.trim();

        // 特殊处理：如果内容包含思考过程（常见于推理模型），尝试提取JSON部分
        // 查找最后一个完整的JSON对象（从最后一个 } 往前找到对应的 {）
        int lastBrace = cleaned.lastIndexOf('}');
        if (lastBrace != -1) {
            // 从lastBrace往前找匹配的 {
            int braceCount = 1;
            int firstBrace = lastBrace - 1;
            while (firstBrace >= 0 && braceCount > 0) {
                if (cleaned.charAt(firstBrace) == '}') {
                    braceCount++;
                } else if (cleaned.charAt(firstBrace) == '{') {
                    braceCount--;
                }
                firstBrace--;
            }
            firstBrace++; // 调整到 { 的位置

            if (firstBrace >= 0 && braceCount == 0) {
                // 找到了完整的JSON对象
                String potentialJson = cleaned.substring(firstBrace, lastBrace + 1);
                // 验证是否像JSON（简单检查：包含引号和冒号）
                if (potentialJson.contains("\"") && potentialJson.contains(":")) {
                    cleaned = potentialJson;
                    log.info("从推理模型输出中提取到JSON，长度: {}", cleaned.length());
                }
            }
        }

        // 如果上面没有找到，使用原来的逻辑：查找第一个 { 和最后一个 }
        if (!cleaned.startsWith("{")) {
            int firstBrace = cleaned.indexOf('{');
            int lastBraceSimple = cleaned.lastIndexOf('}');

            if (firstBrace != -1 && lastBraceSimple != -1 && firstBrace < lastBraceSimple) {
                // 提取 {} 之间的内容
                cleaned = cleaned.substring(firstBrace, lastBraceSimple + 1);
            }
        }

        return cleaned.trim();
    }
}